package org.god.mybatis.core;

import java.lang.reflect.Method;
import java.sql.*;

/**
 * 专门负责执行SQL语句的会话对象
 */
public class SqlSession {
    private SqlSesionFactory factory;

    public SqlSession(SqlSesionFactory factory) {
        this.factory = factory;
    }

    /**
     * 执行insert语句，向数据库中插入数据
     * @param sqlId sql语句的id
     * @param pojo 插入的数据
     * @return
     */
    public int insert(String sqlId,Object pojo){
        int count=0;
        try {
            Connection connection=factory.getTransaction().getConnection();
            // insert into t_user values(#{id},#{name},#{age})
            String godbatisSql=factory.getMapStatements().get(sqlId).getSql();
            // insert into t_user values(?,?,?)
            String sql=godbatisSql.replaceAll("#\\{[a-zA-Z0-9_$]*}","?");
            PreparedStatement pstmt = connection.prepareStatement(sql);
            // 给占位符传值
            // 难度是什么？
            // 第一：不知道有多少个？
            // 第二：不知道该将pojo对象中那个属性赋给哪个？
            // ps.setString(第几个问号，传什么值) 这里都是setString，所有数据库表中的字段类型要求是varchar才行，这是godmybatis的局限性
            int fromIndex=0;
            int index=1;
            while (true){
                int jIndex=godbatisSql.indexOf("#",fromIndex);
                if(jIndex<0){
                    break;
                }
                int yIndex=godbatisSql.indexOf("}",fromIndex);
                String propertyName=godbatisSql.substring(jIndex+2,yIndex).trim();
                fromIndex=yIndex+1;
                // 有属性名，怎么获得id的属性值？调用getId()
                String getMethodName="get"+propertyName.toUpperCase().charAt(0)+propertyName.substring(1);
                Method getMethod = pojo.getClass().getDeclaredMethod(getMethodName);
                Object propertyValue = getMethod.invoke(pojo);
                pstmt.setString(index,propertyValue.toString());
                index++;
            }
            // 执行sql
            count = pstmt.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return count;
    }

    /**
     * 执行查询语句返回一个对象，该方法只适合
     * @param sqlId
     * @param param
     * @return
     */
    public Object selectOne(String sqlId,Object param){
        Object obj=null;
        try {
            Connection connection=factory.getTransaction().getConnection();
            MappedStatement mappedStatement = factory.getMapStatements().get(sqlId);
            // 这个是DQL
            String godbatisSql=mappedStatement.getSql();
            String sql=godbatisSql.replaceAll("#\\{[0-9a-zA-Z_$]*}","?");
            PreparedStatement pstmt = connection.prepareStatement(sql);
            //给占位符赋值
            pstmt.setString(1,param.toString());
            // 查询结果集
            ResultSet rs = pstmt.executeQuery();
            // 要封装的结果集类型
            String resultType=mappedStatement.getResultType();
            // 从结果集取出对象封装
            if(rs.next()){
                // 获取resultType的Class
                Class<?> c = Class.forName(resultType);
                // 调用无参构造方法创建对象
                obj = c.newInstance();
                // 给User类的id，name，age赋值
                ResultSetMetaData rsmd = rs.getMetaData();
                int columnCount = rsmd.getColumnCount();
                for(int i=0;i<columnCount;i++){
                    String propertyName = rsmd.getColumnName(i+1);
                    String setMethodName="set"+propertyName.toUpperCase().charAt(0)+propertyName.substring(1);
                    // 获取set方法
                    Method setMethod = c.getDeclaredMethod(setMethodName, String.class);
                    // 调用set方法给对象obj的属性赋值
                    setMethod.invoke(obj,rs.getString(propertyName));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }

    public void commit(){
        factory.getTransaction().commit();
    }

    public void rollback(){
        factory.getTransaction().rollback();
    }

    public void close(){
        factory.getTransaction().close();
    }

}
